package bupt.xixi.spring;

import bupt.xixi.netty.NettyClient;
import bupt.xixi.netty.NettyServer;
import bupt.xixi.proxy.NettyClientProxyFactory;

import bupt.xixi.registry.IServiceRegistry;
import bupt.xixi.registry.impl.AbstractRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;

@Component
public class SpringBeanPostProcessor implements BeanPostProcessor {

    private static final Logger logger = LoggerFactory.getLogger(SpringBeanPostProcessor.class);

    @Resource
    private NettyClient nettyClient;

    @Resource
    private NettyServer nettyServer;

    @Override
    public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
        // 挑出@RpcService.class, 注册它！
        if (bean.getClass().isAnnotationPresent(RpcService.class)) {
                IServiceRegistry register = nettyServer.getRegister();
                register.registryService(bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        // 挑出bean中的属性值带reference的那个！
        final Class<?> beanClass = bean.getClass();
        final Field[] declaredFields = beanClass.getDeclaredFields();
        for (final Field declaredField : declaredFields) {
            if (declaredField.isAnnotationPresent(RpcReference.class)) {
                final NettyClientProxyFactory clientProxyFactory = new NettyClientProxyFactory(nettyClient);
                final Object clientProxy = clientProxyFactory.getProxy(declaredField.getType());
                declaredField.setAccessible(true); // 让我们在反射时允许设置私有变量
                try {
                    declaredField.set(bean, clientProxy); // 把代理对象赋给反射的值！
                } catch (final IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return bean;
    }
}
